using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using Microsoft.Surface;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;
using System.Collections.ObjectModel;


namespace SurfaceApplicationPhoneBook
{
    /// <summary>
    /// Interaction logic for SurfaceWindow1.xaml
    /// </summary>
    public partial class SurfaceWindow1 : SurfaceWindow
    {
        /// <summary>
        /// Default constructor.
        /// </summary>
       public SurfaceWindow1()
        {
            InitializeComponent();

            // Add handlers for Application activation events
            AddActivationHandlers();
        }


        /// <summary>
        /// Occurs when the window is about to close. 
        /// </summary>
        /// <param name="e"></param>
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            // Remove handlers for Application activation events
            RemoveActivationHandlers();
        }

        /// <summary>
        /// Adds handlers for Application activation events.
        /// </summary>
        private void AddActivationHandlers()
        {
            // Subscribe to surface application activation events
            ApplicationLauncher.ApplicationActivated += OnApplicationActivated;
            ApplicationLauncher.ApplicationPreviewed += OnApplicationPreviewed;
            ApplicationLauncher.ApplicationDeactivated += OnApplicationDeactivated;
        }

        /// <summary>
        /// Removes handlers for Application activation events.
        /// </summary>
        private void RemoveActivationHandlers()
        {
            // Unsubscribe from surface application activation events
            ApplicationLauncher.ApplicationActivated -= OnApplicationActivated;
            ApplicationLauncher.ApplicationPreviewed -= OnApplicationPreviewed;
            ApplicationLauncher.ApplicationDeactivated -= OnApplicationDeactivated;
        }

        /// <summary>
        /// This is called when application has been activated.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnApplicationActivated(object sender, EventArgs e)
        {
            //TODO: enable audio, animations here
        }

        /// <summary>
        /// This is called when application is in preview mode.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnApplicationPreviewed(object sender, EventArgs e)
        {
            //TODO: Disable audio here if it is enabled

            //TODO: optionally enable animations here
        }

        /// <summary>
        ///  This is called when application has been deactivated.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnApplicationDeactivated(object sender, EventArgs e)
        {
            //TODO: disable audio, animations here
        }

        #region Collections

        private ObservableCollection<ContactItem> mobileItems;
        private ObservableCollection<ContactItem> scatterItems;
        private ObservableCollection<ContactItem> pcItems;
        private ObservableCollection<SAGroup> sagroups;

        /// <summary>
        /// Items that bind with the drag source list box.
        /// </summary>
        public ObservableCollection<ContactItem> MobileItems
        {
            get
            {
                if (mobileItems == null)
                {
                    mobileItems = new ObservableCollection<ContactItem>();
                }

                return mobileItems;
            }
        }

        /// <summary>
        /// Items that bind with the drop target list box.
        /// </summary>
        public ObservableCollection<ContactItem> ScatterItems
        {
            get
            {
                if (scatterItems == null)
                {
                    scatterItems = new ObservableCollection<ContactItem>();
                }

                return scatterItems;
            }
        }

        /// <summary>
        /// Items that bind with the drop target list box.
        /// </summary>
        public ObservableCollection<ContactItem> PcItems
        {
            get
            {
                if (pcItems == null)
                {
                    pcItems = new ObservableCollection<ContactItem>();
                }

                return pcItems;
            }
        }

        public ObservableCollection<SAGroup> SAGroups
        {
            get
            {
                if(sagroups == null)
                {
                    sagroups = new ObservableCollection<SAGroup>();
                }
                return sagroups;
            }
        }

        #endregion

        #region Basic Operations

        private void AddMobileItem(ContactItem c)
        {
            if (!MobileItems.Contains(c))
            {
                MobileItems.Add(c);
            }
        }

        private void AddScatterItem(ContactItem c)
        {
            if (!ScatterItems.Contains(c))
            {
                ScatterItems.Add(c);
            }
        }

        private void AddPcItem(ContactItem c)
        {
            if (!PcItems.Contains(c))
            {
                PcItems.Add(c);
            }
        }

        private void RemoveMobileItem(ContactItem c)
        {
            if (MobileItems.Contains(c))
            {
                MobileItems.Remove(c);
            }
        }

        private void RemoveScatterItem(ContactItem c)
        {
            if (ScatterItems.Contains(c))
            {
                ScatterItems.Remove(c);
            }
        }

        private void RemovePcItem(ContactItem c)
        {
            if (PcItems.Contains(c))
            {
                PcItems.Remove(c);
            }
        }

        private ContactItem getContactItemFromScatterViewItem(ScatterViewItem item)
        {

            // Get the name and the firstname within the ScatterViewItem control.
            ContentPresenter content = FindContentPresenter(item);

            if (content == null)
            {
                return null;
            }

            // Get the contact Name
            Label name = null;
            try
            {
                name = (Label)content.ContentTemplate.FindName("namebox", content);
            }
            catch (InvalidCastException ex) { name = null; debug(ex.Message); }

            if (name == null)
            {
                return null;
            }

            String sName = (String)name.Content;

            // Get the contact firstName
            Label firstname = null;
            try
            {
                firstname = (Label)content.ContentTemplate.FindName("firstnamebox", content);
            }
            catch (InvalidCastException ex) { firstname = null; debug(ex.Message); }

            if (firstname == null)
            {
                return null;
            }

            String sFirstName = (String)firstname.Content;

            // Get the contact associated in Items
            ContactItem contactItem = null;
            foreach (ContactItem c in ScatterViewArea.Items)
            {
                if (c.LastName.Equals(sName) && c.FirstName.Equals(sFirstName))
                {
                    contactItem = c;
                }
            }

            return contactItem;
        }

        private ContentPresenter FindContentPresenter(DependencyObject obj)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is System.Windows.Controls.ContentPresenter)
                {
                    return (ContentPresenter)child;
                }
                else
                {
                    ContentPresenter childOfChild = FindContentPresenter(child);
                    if (childOfChild != null)
                    {
                        return childOfChild;
                    }
                }
            }
            return null;
        }

        #endregion

        #region PhoneBook

        // phoneBook declaration
        private PhoneBook.PhoneBook phoneBook = null;

        private PhoneBook.Contact getContactByNameAndFirstName(string name, string firstName)
        {
            foreach (PhoneBook.Contact c in phoneBook.getAllContacts())
            {
                if (c.getPerson().getLastname().Equals(name) && c.getPerson().getFirstname().Equals(firstName))
                {
                    return c;
                }
            }
            return null;
        }
        
        #endregion

        #region OnInitialized
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            DataContext = this;

            // init phoneBook
            phoneBook = new PhoneBook.PhoneBook();

            // get all the groups
            foreach (PhoneBook.Group group in phoneBook.getAllGroups())
            {

                foreach(PhoneBook.Contact c in group.getGroupList())
                {
                    if (c.getPerson().getFirstname().Equals("Homer") && c.getPerson().getLastname().Equals("Simpson"))
                    c.setPictureurl(".\\ImagesContact\\homerSIMPSON.png");
                else if (c.getPerson().getFirstname().Equals("Bart") && c.getPerson().getLastname().Equals("Simpson"))
                    c.setPictureurl(".\\ImagesContact\\bartSIMPSON.png");
                else if (c.getPerson().getFirstname().Equals("Lisa") && c.getPerson().getLastname().Equals("Simpson"))
                    c.setPictureurl(".\\ImagesContact\\lisaSIMPSON.png");
                else if (c.getPerson().getFirstname().Equals("Marge") && c.getPerson().getLastname().Equals("Simpson"))
                    c.setPictureurl(".\\ImagesContact\\margeSIMPSON.png");
                else if (c.getPerson().getFirstname().Equals("Mickey") && c.getPerson().getLastname().Equals("Mouse"))
                    c.setPictureurl(".\\ImagesContact\\mickeyMOUSE.gif");
                else if (c.getPerson().getFirstname().Equals("Donal") && c.getPerson().getLastname().Equals("Duck"))
                    c.setPictureurl(".\\ImagesContact\\donaldDUCK.gif");
                else if (c.getPerson().getFirstname().Equals("Mini") && c.getPerson().getLastname().Equals("Mouse"))
                    c.setPictureurl(".\\ImagesContact\\miniMOUSE.png");
                else if (c.getPerson().getFirstname().Equals("Maggie") && c.getPerson().getLastname().Equals("Simpson"))
                    c.setPictureurl(".\\ImagesContact\\maggieSIMPSON.png");
                else
                    c.setPictureurl(".\\ImagesContact\\contactINCONNU.png");

                
                PcItems.Add(new ContactItem(c.getPictureurl(), c.getPerson().getFirstname(), c.getPerson().getLastname(), c.getHomenum(), c.getOfficenum(), c.getCellnum(), group.getGroupName()));
                }

                SAGroups.Add(new SAGroup(group.getGroupName()));
            }

            // Handlers
            SurfaceDragDrop.AddPreviewDropHandler(LibraryBarPc, OnPC_PreviewDrop);
            SurfaceDragDrop.AddPreviewDropHandler(LibraryBarMobile, OnMobile_PreviewDrop);
            SurfaceDragDrop.AddPreviewDragCanceledHandler(LibraryBarPc, OnDragCanceled);
            SurfaceDragDrop.AddPreviewDragCanceledHandler(LibraryBarMobile, OnDragCanceled);            
        }
        #endregion

        #region Events of the Library Bar

        private void OnPC_PreviewDrop(object sender, SurfaceDragDropEventArgs e)
        {
            if (LibraryBarMobile.IsAncestorOf(e.Cursor.DragSource))
            {
                e.Effects = DragDropEffects.Move;
            }

            // Update the PC storage items     
            RemovePcItem((ContactItem)e.Cursor.Data);
            AddPcItem((ContactItem)e.Cursor.Data);            
        }
        
        private void OnMobile_PreviewDrop(object sender, SurfaceDragDropEventArgs e)
        {            
            if (LibraryBarPc.IsAncestorOf(e.Cursor.DragSource))
            {                
                e.Effects = DragDropEffects.Copy;
            }             
        }

        private void OnDragCanceled(object sender, SurfaceDragDropEventArgs e)
        {
            try {                
                AddScatterItem((ContactItem)e.Cursor.Data);               
            } catch(InvalidCastException ex) { debug(ex.Message); }
        }

        #endregion

        #region Buttons Click Events

        private void SurfaceButtonOk_Click(object sender, RoutedEventArgs e)
        {

            Button button = (Button)e.Source as Button;
            ScatterViewItem item = (ScatterViewItem)ScatterViewArea.ContainerFromElement(button);

            ContactItem contactItem = getContactItemFromScatterViewItem(item);
            
            if (contactItem == null)
            {
                return;
            }            
                
            // Update the fields of this contact in the ScatterViewItem and in the application

            // Get the name and the firstname within the ScatterViewItem control.
            ContentPresenter content = FindContentPresenter(item);

            if (content == null)
            {
                return;
            }
                
            // Get the home num
            SurfaceTextBox homeNum = (SurfaceTextBox)content.ContentTemplate.FindName("homenumbox", content);

            // Get the office num
            SurfaceTextBox officeNum = (SurfaceTextBox)content.ContentTemplate.FindName("officenumbox", content);
                
            // Get the cell num
            SurfaceTextBox cellNum = (SurfaceTextBox)content.ContentTemplate.FindName("cellnumbox", content);

            PhoneBook.Contact contactPhoneBook = getContactByNameAndFirstName(contactItem.LastName, contactItem.FirstName);

            // The contact is not in the application
            if (contactPhoneBook == null)
            {
                item.Visibility = Visibility.Hidden;
                return;
            }

            PhoneBook.Contact newContact = contactPhoneBook;

            // Update the home num
            if (homeNum != null)
            {
                contactItem.HomeNum = homeNum.Text;
                newContact.setHomenum(homeNum.Text);                    
            }

            // Update the office num
            if (officeNum != null)
            {
                contactItem.OfficeNum = officeNum.Text;
                newContact.setOfficenum(officeNum.Text);
            }

            // Update the cell num
            if (cellNum != null)
            {
                contactItem.CellNum = cellNum.Text;
                newContact.setCellnum(cellNum.Text);
            }

            phoneBook.modifyContact(contactPhoneBook, newContact);

            // Update the group
            PhoneBook.Group group = phoneBook.getGroupByContact(newContact);

            if (group != null)
            {
                if(!contactItem.Group.Equals(group.getGroupName()))
                {
                    foreach (PhoneBook.Group g in phoneBook.getAllGroups())
                    {
                        if (g.getGroupName().Equals(contactItem.Group))
                        {
                            group.removeFromGroup(newContact);
                            g.addToGroup(newContact);

                            // Update the mobileItems List if necessary
                            if (MobileItems.Contains(contactItem))
                            {
                                RemoveMobileItem(contactItem);
                                AddMobileItem(contactItem);
                            }
                            else
                            {
                                // Update the PcItems List
                                RemovePcItem(contactItem);
                                AddPcItem(contactItem);
                            }
                            break;
                        }
                    }
                }
            }
                        
            // Remove the contact from the ScatterViewArea
            RemoveScatterItem(contactItem);

            // Delete the item    
            item.Visibility = Visibility.Hidden;                         
        }

        private void SurfaceButtonCancel_Click(object sender, RoutedEventArgs e)
        {
            Button button = (Button)e.Source as Button;
            ScatterViewItem item = (ScatterViewItem)ScatterViewArea.ContainerFromElement(button);

            ContactItem contactItem = getContactItemFromScatterViewItem(item);

            if (contactItem == null)
            {
                return;
            }

            // Reset the contact item  

            PhoneBook.Contact contactPhoneBook = getContactByNameAndFirstName(contactItem.LastName, contactItem.FirstName);

            // The contact doesn't exist in the application
            if (contactPhoneBook == null)
            {
                item.Visibility = Visibility.Hidden;
                return;
            }

            contactItem.HomeNum = contactPhoneBook.getHomenum();
            contactItem.OfficeNum = contactPhoneBook.getOfficenum();
            contactItem.CellNum = contactPhoneBook.getCellnum();
            
            PhoneBook.Group g = phoneBook.getGroupByContact(contactPhoneBook);
            if(g != null)
            {
                contactItem.Group = g.getGroupName();
            }

            // Remove the contact from the ScatterViewArea
            RemoveScatterItem(contactItem);

            // Delete the item                
            item.Visibility = Visibility.Hidden;                        
        }

        private void ElementMenuItem_ClickFamily(object sender, RoutedEventArgs e)
        {
            ElementMenuItem element = (ElementMenuItem)e.Source as ElementMenuItem;
            ScatterViewItem item = (ScatterViewItem)ScatterViewArea.ContainerFromElement(element);

            ContactItem contactItem = getContactItemFromScatterViewItem(item);

            if (contactItem == null)
            {
                return;
            }

            PhoneBook.Contact contactPhoneBook = getContactByNameAndFirstName(contactItem.LastName, contactItem.FirstName);

            // The contact doesn't exist in the application
            if (contactPhoneBook == null)
            {
                item.Visibility = Visibility.Hidden;
                return;
            }

            // Update the group
            contactItem.Group = "Family";
        }

        private void ElementMenuItem_ClickFriends(object sender, RoutedEventArgs e)
        {
            ElementMenuItem element = (ElementMenuItem)e.Source as ElementMenuItem;
            ScatterViewItem item = (ScatterViewItem)ScatterViewArea.ContainerFromElement(element);

            ContactItem contactItem = getContactItemFromScatterViewItem(item);

            if (contactItem == null)
            {
                return;
            }

            PhoneBook.Contact contactPhoneBook = getContactByNameAndFirstName(contactItem.LastName, contactItem.FirstName);

            // The contact doesn't exist in the application
            if (contactPhoneBook == null)
            {
                item.Visibility = Visibility.Hidden;
                return;
            }

            // Update the group
            contactItem.Group = "Friends";
        }

        private void ElementMenuItem_ClickBusiness(object sender, RoutedEventArgs e)
        {
            ElementMenuItem element = (ElementMenuItem)e.Source as ElementMenuItem;
            ScatterViewItem item = (ScatterViewItem)ScatterViewArea.ContainerFromElement(element);

            ContactItem contactItem = getContactItemFromScatterViewItem(item);

            if (contactItem == null)
            {
                return;
            }

            PhoneBook.Contact contactPhoneBook = getContactByNameAndFirstName(contactItem.LastName, contactItem.FirstName);

            // The contact doesn't exist in the application
            if (contactPhoneBook == null)
            {
                item.Visibility = Visibility.Hidden;
                return;
            }

            // Update the group
            contactItem.Group = "Business";
        }        

        #endregion
        
        #region Debug
        private void debug(string t) { Console.WriteLine("[DEBUG: " + t + "]"); }
        private void writeList(ObservableCollection<ContactItem> list)
        {
            Console.WriteLine("[List :");
            foreach (ContactItem c in list) { Console.WriteLine(" ** " + c); }
            Console.WriteLine("]");
        }
        #endregion

    }
}